﻿using ConfigCreate.Model;
using System;
using System.Collections.Generic;
using System.Drawing.Imaging;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
using static System.Environment;
using Brush = System.Windows.Media.Brush;
using HorizontalAlignment = System.Windows.HorizontalAlignment;
using MessageBox = System.Windows.MessageBox;

namespace ConfigCreate
{
    /// <summary>
    /// ConfigWin.xaml 的交互逻辑
    /// </summary>
    public partial class ConfigWin : Window
    {
        /// <summary>
        /// 配置保存时参数变化通过事件
        /// </summary>
        public event EventHandler<ParameterChange[]>? SaveParametersChange;
        /// <summary>
        /// 窗口关闭前调用
        /// </summary>
        public event EventHandler<bool>? WinClosed;

        /// <summary>
        /// 动态绑定通知
        /// </summary>
        public Action<DynamicBindingRoutePath[]>? DynamicBindingNotification { get; set; }

        private bool is_dialog = false;

        static ConfigWin()
        {
            
        }

        /// <summary>
        /// 初始动态动态对话框
        /// </summary>
        public ConfigWin()
        {
            InitializeComponent();

            cpanel.SaveParametersChange += (sender, e) =>
            {
                SaveParametersChange?.Invoke(this, e);
            };
        }

        /// <summary>
        /// 默认开启安全拷贝机制，只有在保存时才真正更新到对象上
        /// </summary>
        public bool SafeCopyInstance
        {
            get { return cpanel.SafeCopyInstance; }
            set { cpanel.SafeCopyInstance = value; }
        }

        /// <summary>
        /// 动态绑定路径
        /// </summary>
        public DynamicBindingRoutePath[]? DynamicBindings
        {
            get
            {
                return cpanel.DynamicBindings;
            }
        }

        private double title_width = 120d;
        /// <summary>
        /// 标题栏宽度
        /// </summary>
        public double TitleWidth
        {
            get { return title_width; }
            set
            {
                title_width = value;
                cpanel.SetPanelTitleWidht(title_width);
            }
        }

        #region 添加控件

        /// <summary>
        /// 添加文本框
        /// </summary>
        /// <param name="header_name">大类别名</param>
        /// <param name="group_name">组名</param>
        /// <param name="binding_object">绑定对象</param>
        /// <param name="property_path">上面对象的属性名</param>
        /// <param name="title">标题</param>
        /// <param name="placeholder">提示占位符</param>
        /// <param name="text_lenght">文本框中字符长度</param>
        /// <param name="show_clear_button">是否显示清空按钮</param>
        /// <param name="is_readonly">是否为只读</param>
        /// <param name="is_multiline">是否多行文本</param>
        /// <param name="height">文本高度</param>
        /// <param name="group_index">组排序索引</param>
        /// <param name="header_index">大类别排序索引</param>
        /// <param name="necessary">是否为必填项</param>
        /// <param name="remark">备注</param>
        /// <param name="save_config">该属性是否在保存时保存到配置中</param>
        public void AddTextBox(string header_name, string group_name, object binding_object, string property_path, string title, string? placeholder = null, int? text_lenght = null, bool show_clear_button = true, bool is_readonly = false, bool is_multiline = false, double height = 60d, int? group_index = null, int? header_index = null, bool necessary = false, string? remark = null, bool save_config = true)
        {
            cpanel.AddTextBox(header_name, group_name, binding_object, property_path, title, placeholder, text_lenght, show_clear_button, is_readonly, is_multiline, height, group_index, header_index, necessary, remark, save_config);
        }

        /// <summary>
        /// 添加数字框
        /// </summary>
        /// <param name="header_name">大类别名</param>
        /// <param name="group_name">组名</param>
        /// <param name="binding_object">绑定对象</param>
        /// <param name="property_path">上面对象的属性名</param>
        /// <param name="title">标题</param>
        /// <param name="placeholder">提示占位符</param>
        /// <param name="decimal_places">小数点多少位</param>
        /// <param name="increment">获取或设置单击向上或向下按钮时，数字显示框（也称作 up-down 控件）递增或递减的值</param>
        /// <param name="maximum">获取或设置最大允许值</param>
        /// <param name="minimum">获取或设置最小允许值</param>
        /// <param name="value_format">数字显示格式</param>
        /// <param name="show_clear_button">是否显示清除按钮</param>
        /// <param name="is_readonly">是否为只读</param>
        /// <param name="rule">数据验证</param>
        /// <param name="group_index">组排序索引</param>
        /// <param name="header_index">大类别排序索引</param>
        /// <param name="necessary">是否为必填项</param>
        /// <param name="remark">备注</param>
        /// <param name="save_config">该属性是否在保存时保存到配置中</param>
        public void AddNumeric(string header_name, string group_name, object binding_object, string property_path, string title, string? placeholder = null, int? decimal_places = null, double? increment = null, double? maximum = null, double? minimum = null, string? value_format = null, bool show_clear_button = false, bool is_readonly = false, ValidationRule? rule = null, int? group_index = null, int? header_index = null, bool necessary = false, string? remark = null, bool save_config = true)
        {
            cpanel.AddNumeric(header_name, group_name, binding_object, property_path, title, placeholder, decimal_places, increment, maximum, minimum, value_format, show_clear_button, is_readonly, rule, group_index, header_index, necessary, remark, save_config);
        }

        /// <summary>
        /// 添加切换按钮
        /// </summary>
        /// <param name="header_name">大类别名</param>
        /// <param name="group_name">组名</param>
        /// <param name="binding_object">绑定对象</param>
        /// <param name="property_path">上面对象的属性名</param>
        /// <param name="title">标题</param>
        /// <param name="checked_txt">选择时显示的文本</param>
        /// <param name="unchecked_txt">未选择时显示的文本</param>
        /// <param name="group_index">组排序索引</param>
        /// <param name="header_index">大类别排序索引</param>
        /// <param name="necessary">是否为必填项</param>
        /// <param name="remark">备注</param>
        /// <param name="save_config">该属性是否在保存时保存到配置中</param>
        public void AddToggleButton(string header_name, string group_name, object binding_object, string property_path, string title, string? checked_txt = null, string? unchecked_txt = null, int? group_index = null, int? header_index = null, bool necessary = false, string? remark = null, bool save_config = true)
        {
            cpanel.AddToggleButton(header_name, group_name, binding_object, property_path, title, checked_txt, unchecked_txt, group_index, header_index, necessary, remark, save_config);
        }

        /// <summary>
        /// 添加密码框
        /// </summary>
        /// <param name="header_name">大类别名</param>
        /// <param name="group_name">组名</param>
        /// <param name="binding_object">绑定对象</param>
        /// <param name="property_path">上面对象的属性名</param>
        /// <param name="title">标题</param>
        /// <param name="placeholder">提示占位符</param>
        /// <param name="password_len">密码框字符长度</param>
        /// <param name="show_eye_button">是否显示查看密码按钮</param>
        /// <param name="show_clear_button">是否显示清空按钮</param>
        /// <param name="password_char">密码字符</param>
        /// <param name="group_index">组排序索引</param>
        /// <param name="header_index">大类别排序索引</param>
        /// <param name="necessary">是否为必填项</param>
        /// <param name="remark">备注</param>
        /// <param name="save_config">该属性是否在保存时保存到配置中</param>
        public void AddPasswordBox(string header_name, string group_name, object binding_object, string property_path, string title, string? placeholder = null, int? password_len = null, bool show_eye_button = true, bool show_clear_button = true, char? password_char = null, int? group_index = null, int? header_index = null, bool necessary = false, string? remark = null, bool save_config = true)
        {
            cpanel.AddPasswordBox(header_name, group_name, binding_object, property_path, title, placeholder, password_len, show_eye_button, show_clear_button, password_char, group_index, header_index, necessary, remark, save_config);
        }

        /// <summary>
        /// 添加组合框
        /// </summary>
        /// <param name="header_name">大类别名</param>
        /// <param name="group_name">组名</param>
        /// <param name="binding_object">绑定对象</param>
        /// <param name="property_path">上面对象的属性名</param>
        /// <param name="title">标题</param>
        /// <param name="item_type">添加项类型</param>
        /// <param name="tl">数据源</param>
        /// <param name="group_index">组排序索引</param>
        /// <param name="header_index">大类别排序索引</param>
        /// <param name="necessary">是否为必填项</param>
        /// <param name="remark">备注</param>
        /// <param name="save_config">该属性是否在保存时保存到配置中</param>
        public void AddComboBox(string header_name, string group_name, object binding_object, string property_path, string title, Type item_type, List<ComboBoxData> tl, int? group_index = null, int? header_index = null, bool necessary = false, string? remark = null, bool save_config = true)
        {
            cpanel.AddComboBox(header_name, group_name, binding_object, property_path, title, item_type, tl, group_index, header_index, necessary, remark, save_config);
        }

        /// <summary>
        /// 添加日期选择框
        /// </summary>
        /// <param name="header_name">大类别名</param>
        /// <param name="group_name">组名</param>
        /// <param name="binding_object">绑定对象</param>
        /// <param name="property_path">上面对象的属性名</param>
        /// <param name="title">标题</param>
        /// <param name="group_index">组排序索引</param>
        /// <param name="header_index">大类别排序索引</param>
        /// <param name="necessary">是否为必填项</param>
        /// <param name="remark">备注</param>
        /// <param name="save_config">该属性是否在保存时保存到配置中</param>
        public void AddDatePicker(string header_name, string group_name, object binding_object, string property_path, string title, int? group_index = null, int? header_index = null, bool necessary = false, string? remark = null, bool save_config = true)
        {
            cpanel.AddDatePicker(header_name, group_name, binding_object, property_path, title, group_index, header_index, necessary, remark, save_config); ;
        }

        /// <summary>
        /// 添加日期时间选择框
        /// </summary>
        /// <param name="header_name">大类别名</param>
        /// <param name="group_name">组名</param>
        /// <param name="binding_object">绑定对象</param>
        /// <param name="property_path">上面对象的属性名</param>
        /// <param name="title">标题</param>
        /// <param name="date_timeformat">日期显示格式</param>
        /// <param name="group_index">组排序索引</param>
        /// <param name="header_index">大类别排序索引</param>
        /// <param name="necessary">是否为必填项</param>
        /// <param name="remark">备注</param>
        /// <param name="save_config">该属性是否在保存时保存到配置中</param>
        public void AddDateTimePicker(string header_name, string group_name, object binding_object, string property_path, string title, string? date_timeformat = null, int? group_index = null, int? header_index = null, bool necessary = false, string? remark = null, bool save_config = true)
        {
            cpanel.AddDateTimePicker(header_name, group_name, binding_object, property_path, title, date_timeformat, group_index, header_index, necessary, remark, save_config);
        }

        /// <summary>
        /// 添加多选组合框
        /// </summary>
        /// <param name="header_name">大类别名</param>
        /// <param name="group_name">组名</param>
        /// <param name="binding_object">绑定对象</param>
        /// <param name="property_path">上面对象的属性名</param>
        /// <param name="title">标题</param>
        /// <param name="item_type">子项类型</param>
        /// <param name="tl">数据源</param>
        /// <param name="show_select_all_button">是否显示选择所有框</param>
        /// <param name="show_clear_button">是否显示清空按钮</param>
        /// <param name="group_index">组排序索引</param>
        /// <param name="header_index">大类别排序索引</param>
        /// <param name="necessary">是否为必填项</param>
        /// <param name="remark">备注</param>
        /// <param name="save_config">该属性是否在保存时保存到配置中</param>
        public void AddMultipleComboBox(string header_name, string group_name, object binding_object, string property_path, string title, Type item_type, List<ComboBoxData> tl, bool show_select_all_button = true, bool show_clear_button = true, int? group_index = null, int? header_index = null, bool necessary = false, string? remark = null, bool save_config = true)
        {
            cpanel.AddMultipleComboBox(header_name, group_name, binding_object, property_path, title, item_type, tl, show_select_all_button, show_clear_button, group_index, header_index, necessary, remark, save_config);
        }

        /// <summary>
        /// 添加IP地址框
        /// </summary>
        /// <param name="header_name">大类别名</param>
        /// <param name="group_name">组名</param>
        /// <param name="binding_object">绑定对象</param>
        /// <param name="property_path">上面对象的属性名</param>
        /// <param name="title">标题</param>
        /// <param name="is_readonly">是否只读模式</param>
        /// <param name="group_index">组排序索引</param>
        /// <param name="header_index">大类别排序索引</param>
        /// <param name="necessary">是否为必填项</param>
        /// <param name="remark">备注</param>
        /// <param name="save_config">该属性是否在保存时保存到配置中</param>
        public void AddIpAddressTextBox(string header_name, string group_name, object binding_object, string property_path, string title, bool is_readonly = false, int? group_index = null, int? header_index = null, bool necessary = false, string? remark = null, bool save_config = true)
        {
            cpanel.AddIpAddressTextBox(header_name, group_name, binding_object, property_path, title, is_readonly, group_index, header_index, necessary, remark, save_config);
        }

        /// <summary>
        /// 添加打开文本选择框
        /// </summary>
        /// <param name="header_name">大类别名</param>
        /// <param name="group_name">组名</param>
        /// <param name="binding_object">绑定对象</param>
        /// <param name="property_path">上面对象的属性名</param>
        /// <param name="title">标题</param>
        /// <param name="dialog_title">打开对话框标题</param>
        /// <param name="dialog_filter">打开对话框过滤项</param>
        /// <param name="is_multiselect">是否为多选</param>
        /// <param name="is_readonly">其中文本框是否只读</param>
        /// <param name="group_index">组排序索引</param>
        /// <param name="header_index">大类别排序索引</param>
        /// <param name="necessary">是否为必填项</param>
        /// <param name="remark">备注</param>
        /// <param name="save_config">该属性是否在保存时保存到配置中</param>
        public void AddOpenFile(string header_name, string group_name, object binding_object, string property_path, string title, string? dialog_title = null, string? dialog_filter = null, bool is_multiselect = false, bool is_readonly = false, int? group_index = null, int? header_index = null, bool necessary = false, string? remark = null, bool save_config = true)
        {
            cpanel.AddOpenFile(header_name, group_name, binding_object, property_path, title, dialog_title, dialog_filter, is_multiselect, is_readonly, group_index, header_index, necessary, remark, save_config);
        }

        /// <summary>
        /// 添加文本保存对话框
        /// </summary>
        /// <param name="header_name">大类别名</param>
        /// <param name="group_name">组名</param>
        /// <param name="binding_object">绑定对象</param>
        /// <param name="property_path">上面对象的属性名</param>
        /// <param name="title">标题</param>
        /// <param name="dialog_title">对话框标题</param>
        /// <param name="dialog_filter">对话框过滤项</param>
        /// <param name="is_readonly">其中文本框是否只读</param>
        /// <param name="default_ext">默认扩展名</param>
        /// <param name="initial_directory">初始化目录</param>
        /// <param name="group_index">组排序索引</param>
        /// <param name="header_index">大类别排序索引</param>
        /// <param name="necessary">是否为必填项</param>
        /// <param name="remark">备注</param>
        /// <param name="save_config">该属性是否在保存时保存到配置中</param>
        public void AddSaveFile(string header_name, string group_name, object binding_object, string property_path, string title, string? dialog_title = null, string? dialog_filter = null, bool is_readonly = false, string? default_ext = null, string? initial_directory = null, int? group_index = null, int? header_index = null, bool necessary = false, string? remark = null, bool save_config = true)
        {
            cpanel.AddSaveFile(header_name, group_name, binding_object, property_path, title, dialog_title, dialog_filter, is_readonly, default_ext, initial_directory, group_index, header_index, necessary, remark, save_config);
        }

        /// <summary>
        /// 添加目录选择框
        /// </summary>
        /// <param name="header_name">大类别名</param>
        /// <param name="group_name">组名</param>
        /// <param name="binding_object">绑定对象</param>
        /// <param name="property_path">上面对象的属性名</param>
        /// <param name="title">标题</param>
        /// <param name="dialog_description">对话框标题</param>
        /// <param name="show_new_folder_button">是否显示新建文件夹按钮</param>
        /// <param name="root_folder">对话框根目录</param>
        /// <param name="is_readonly">其中文本框是否只读</param>
        /// <param name="group_index">组排序索引</param>
        /// <param name="header_index">大类别排序索引</param>
        /// <param name="necessary">是否为必填项</param>
        /// <param name="remark">备注</param>
        /// <param name="save_config">该属性是否在保存时保存到配置中</param>
        public void AddOpenFolder(string header_name, string group_name, object binding_object, string property_path, string title, string? dialog_description = null, bool show_new_folder_button = true, SpecialFolder root_folder = SpecialFolder.Desktop, bool is_readonly = false, int? group_index = null, int? header_index = null, bool necessary = false, string? remark = null, bool save_config = true)
        {
            cpanel.AddOpenFolder(header_name, group_name, binding_object, property_path, title, dialog_description, show_new_folder_button, root_folder, is_readonly, group_index, header_index, necessary, remark, save_config);
        }

        /// <summary>
        /// 添加标签框控件
        /// </summary>
        /// <param name="header_name">大类别名</param>
        /// <param name="group_name">组名</param>
        /// <param name="binding_object">绑定对象</param>
        /// <param name="property_path">上面对象的属性名</param>
        /// <param name="style_key">样式Key</param>
        /// <param name="horizontal_alignment">横向靠齐方式</param>
        /// <param name="font_size">文字大小</param>
        /// <param name="foreground">前渲染</param>
        /// <param name="background">背景渲染</param>
        /// <param name="font_weight">文字样式</param>
        /// <param name="font_family">文字字体</param>
        /// <param name="group_index">组排序索引</param>
        /// <param name="header_index">大类别排序索引</param>
        /// <param name="remark">备注</param>
        /// <param name="save_config">该属性是否在保存时保存到配置中</param>
        public void AddTextBlock(string header_name, string group_name, object binding_object, string property_path, string? style_key = null, HorizontalAlignment horizontal_alignment = HorizontalAlignment.Left, double? font_size = null, Brush? foreground = null, Brush? background = null, string? font_weight = null, string? font_family = null, int? group_index = null, int? header_index = null, string? remark = null, bool save_config = true)
        {
            cpanel.AddTextBlock(header_name, group_name, binding_object, property_path, style_key, horizontal_alignment, font_size, foreground, background, font_weight, font_family, group_index, header_index, remark, save_config);
        }

        /// <summary>
        /// 添加自定义控件
        /// </summary>
        /// <param name="header_name">大类别名</param>
        /// <param name="group_name">组名</param>
        /// <param name="binding_object">绑定对象</param>
        /// <param name="property_path">上面对象的属性名</param>
        /// <param name="title">标题</param>
        /// <param name="group_index">组排序索引</param>
        /// <param name="header_index">大类别排序索引</param>
        /// <param name="remark">备注</param>
        /// <param name="save_config">该属性是否在保存时保存到配置中</param>
        public void AddCustomControl(string header_name, string group_name, object binding_object, string property_path, string? title = null, int? group_index = null, int? header_index = null, string? remark = null, bool save_config = true)
        {
            cpanel.AddCustomControl(header_name, group_name, binding_object, property_path, title, group_index, header_index, remark, save_config);
        }

        #endregion

        #region 绑定

        /// <summary>
        /// 设置或添加控件的绑定模式
        /// </summary>
        /// <param name="header_name">大类别名</param>
        /// <param name="group_name">组名</param>
        /// <param name="property_path">绑定对象的属性名</param>
        /// <param name="binding_route_path">绑定路由</param>
        /// <param name="binding_data_func">生成绑定数据源的函数</param>
        /// <param name="default_binding">是否默认显示绑定模式</param>
        /// <param name="show_switch_button">是否显示模式切换按钮</param>
        /// <param name="title">标题</param>
        /// <param name="group_index">组排序索引</param>
        /// <param name="header_index">大类别排序索引</param>
        /// <param name="necessary">是否为必填项</param>
        /// <param name="remark">备注</param>
        /// <param name="save_config">该属性是否在保存时保存到配置中</param>
        public void AddOrSetBindingPanel(string header_name, string group_name, string property_path, string binding_route_path, Func<object, GroupHeader, List<BindingData>> binding_data_func, bool default_binding = true, bool show_switch_button = true, string title = "未设置标题", int? group_index = null, int? header_index = null, bool? necessary = null, string? remark = null, bool save_config = true)
        {
            cpanel.AddOrSetBindingPanel(header_name, group_name, property_path, binding_route_path, binding_data_func, default_binding, show_switch_button, title, group_index, header_index, necessary, remark, save_config);
        }

        /// <summary>
        /// 设置或添加控件的绑定模式
        /// </summary>
        /// <param name="header_name">大类别名</param>
        /// <param name="group_name">组名</param>
        /// <param name="property_path">绑定对象的属性名</param>
        /// <param name="binding_route_path">绑定路由</param>
        /// <param name="binding_data">绑定列表</param>
        /// <param name="default_binding">是否默认显示绑定模式</param>
        /// <param name="show_switch_button">是否显示模式切换按钮</param>
        /// <param name="title">标题</param>
        /// <param name="group_index">组排序索引</param>
        /// <param name="header_index">大类别排序索引</param>
        /// <param name="necessary">是否为必填项</param>
        /// <param name="remark">备注</param>
        /// <param name="save_config">该属性是否在保存时保存到配置中</param>
        public void AddOrSetBindingPanel(string header_name, string group_name, string property_path, string binding_route_path, List<BindingData> binding_data, bool default_binding = true, bool show_switch_button = true, string title = "未设置标题", int? group_index = null, int? header_index = null, bool? necessary = null, string? remark = null, bool save_config = true)
        {
            cpanel.AddOrSetBindingPanel(header_name, group_name, property_path, binding_route_path, binding_data, default_binding, show_switch_button, title, group_index, header_index, necessary, remark, save_config);
        }

        #endregion

        #region 权限设置

        /// <summary>
        /// 设置控件权限
        /// </summary>
        /// <param name="header_name">大类别名</param>
        /// <param name="group_name">组名</param>
        /// <param name="property_path">绑定对象的属性名</param>
        /// <param name="role_name">角色名</param>
        /// <param name="type">设置类型，不可见或不可用</param>
        /// <returns></returns>
        public bool SetRolePermissionPanel(string header_name, string group_name, string property_path, string role_name, RolePermissionType type = RolePermissionType.Invisible)
        {
            return cpanel.SetRolePermissionPanel(header_name, group_name, property_path, role_name, type);
        }

        /// <summary>
        /// 设置组权限
        /// </summary>
        /// <param name="header_name">大类别名</param>
        /// <param name="group_name">组名</param>
        /// <param name="role_name">角色名</param>
        /// <param name="type">设置类型，不可见或不可用</param>
        /// <returns></returns>
        public bool SetRolePermissionGroup(string header_name, string group_name, string role_name, RolePermissionType type = RolePermissionType.Invisible)
        {
            return cpanel.SetRolePermissionGroup(header_name, group_name, role_name, type);
        }

        /// <summary>
        /// 设置大类别权限
        /// </summary>
        /// <param name="header_name">大类别名</param>
        /// <param name="role_name">角色名</param>
        /// <param name="type">设置类型，不可见或不可用</param>
        /// <returns></returns>
        public bool SetRolePermissionHeader(string header_name, string role_name, RolePermissionType type = RolePermissionType.Invisible)
        {
            return cpanel.SetRolePermissionHeader(header_name, role_name, type);
        }

        #endregion

        #region 其它设置

        /// <summary>
        /// 设置控件值修改通知
        /// </summary>
        /// <param name="header_name">大类别名</param>
        /// <param name="group_name">组名</param>
        /// <param name="property_path">绑定对象的属性名</param>
        /// <param name="definition">通知时控件标识</param>
        /// <returns></returns>
        public bool SetEditNotificationPanel(string header_name, string group_name, string property_path, string? definition = null)
        {
            return cpanel.SetEditNotificationPanel(header_name, group_name, property_path, definition);
        }

        /// <summary>
        /// 控制控件的可见性
        /// </summary>
        /// <param name="header_name">大类别名</param>
        /// <param name="group_name">组名</param>
        /// <param name="property_path">绑定对象的属性名</param>
        /// <param name="binding_property_path">用于关联控制的同组属性的属性名</param>
        /// <param name="value">关联控制属性的检查值</param>
        /// <param name="is_reversal">是否条件反转</param>
        /// <returns></returns>
        public bool SetVisibilityPanel(string header_name, string group_name, string property_path, string binding_property_path, object value, bool is_reversal = false)
        {
            return cpanel.SetVisibilityPanel(header_name, group_name, property_path, binding_property_path, value, is_reversal);
        }

        /// <summary>
        /// 控制控件的可见性
        /// </summary>
        /// <param name="header_name">大类别名</param>
        /// <param name="group_name">组名</param>
        /// <param name="property_path">绑定对象的属性名</param>
        /// <param name="binding_header_name">用于关联控制属性所在大类别名</param>
        /// <param name="binding_group_name">用于关联控制属性所在的组名</param>
        /// <param name="binding_property_path">用于关联控制属性的属性名</param>
        /// <param name="value">关联控制属性的检查值</param>
        /// <param name="is_reversal">是否条件反转</param>
        /// <returns></returns>
        public bool SetVisibilityPanel(string header_name, string group_name, string property_path, string binding_header_name, string binding_group_name, string binding_property_path, object value, bool is_reversal = false)
        {
            return cpanel.SetVisibilityPanel(header_name, group_name, property_path, binding_header_name, binding_group_name, binding_property_path, value, is_reversal);
        }

        /// <summary>
        /// 控制组的可见性
        /// </summary>
        /// <param name="header_name">大类别名</param>
        /// <param name="group_name">组名</param>
        /// <param name="binding_header_name">用于关联控制属性所在大类别名</param>
        /// <param name="binding_group_name">用于关联控制属性所在的组名</param>
        /// <param name="binding_property_path">用于关联控制属性的属性名</param>
        /// <param name="value">关联控制属性的检查值</param>
        /// <param name="is_reversal">是否条件反转</param>
        /// <returns></returns>
        public bool SetVisibilityGroup(string header_name, string group_name, string binding_header_name, string binding_group_name, string binding_property_path, object value, bool is_reversal = false)
        {
            return cpanel.SetVisibilityGroup(header_name, group_name, binding_header_name, binding_group_name, binding_property_path, value, is_reversal);
        }

        /// <summary>
        /// 添加保存时各控件时数值的检查
        /// </summary>
        /// <param name="func">检查函数</param>
        public void AddSelfCheckFunc(Func<string> func)
        {
            cpanel.AddSelfCheckFunc(func);
        }

        /// <summary>
        /// 设置组排序和宽高
        /// </summary>
        /// <param name="header_name">大类别名</param>
        /// <param name="group_name">组名</param>
        /// <param name="dock">设置组的依靠</param>
        /// <param name="group_width">组宽度</param>
        /// <param name="group_height">组高度</param>
        /// <param name="parent_key">父容器Key</param>
        /// <returns></returns>
        public bool SetDockPanelGroup(string header_name, string group_name, Dock dock, double group_width = double.NaN, double group_height = double.NaN, string? parent_key = null)
        {
            return cpanel.SetDockPanelGroup(header_name, group_name, dock, group_width, group_height);
        }

        /// <summary>
        /// 添加DockPanel面板
        /// </summary>
        /// <param name="header_name">大类别名</param>
        /// <param name="dockpane_key">DockPanel面板Key</param>
        /// <param name="dock">依靠方式</param>
        /// <param name="width">面板宽度</param>
        /// <param name="height">面板高度</param>
        /// <param name="parent_key">面板的父容器Key</param>
        /// <returns></returns>
        public bool AddDockPanel(string header_name, string dockpane_key, Dock dock, double width = double.NaN, double height = double.NaN, string? parent_key = null)
        {
            return cpanel.AddDockPanel(header_name, dockpane_key, dock, width, height, parent_key);
        }

        #endregion

        /// <summary>
        /// 扫描类实例来添加控件并设置控件
        /// </summary>
        /// <typeparam name="T">类</typeparam>
        /// <param name="class_obj">类对象</param>
        /// <param name="scan_children">是否扫描子属性</param>
        /// <param name="null_for_create">如果子属性值为空是否自动创建</param>
        /// <param name="config_file">配置存储位置</param>
        /// <param name="action">添加控件后执行的代码</param>
        public bool AddControlSource<T>(T class_obj, bool scan_children = true, bool null_for_create = true, string? config_file = null, Action? action = null) where T : class
        {
            if (!cpanel.AddControlSource<T>(class_obj, out string errmsg, scan_children, null_for_create, config_file, action))
            {
                MessageBox.Show(errmsg, "加载控件出错", MessageBoxButton.OK, MessageBoxImage.Stop);
                this.Close();
                return false;
            }
            return true;
        }

        /// <summary>
        /// 获取真实绑定对象
        /// </summary>
        /// <typeparam name="T">类型</typeparam>
        /// <param name="binding_object">原始对象</param>
        /// <returns>返回绑定对象</returns>
        public T? GetBindingObject<T>(T binding_object) where T : class
        {
            return cpanel.GetBindingObject<T>(binding_object);
        }

        /// <summary>
        /// 通过绑定状态配置文件生成对应框
        /// </summary>
        /// <param name="dynamic_binding_config_file">保存和还原动态绑定的文件</param>
        /// <param name="safe_copy_instance">安全拷贝，按确认才生效</param>
        /// <param name="role_name">角色名</param>
        public void ShowWinWithConfigFile(string dynamic_binding_config_file, bool safe_copy_instance = true, string? role_name = null)
        {
            //b_close.Visibility = safe_copy_instance ? Visibility.Visible : Visibility.Collapsed;
            cpanel.ShowControlsWithConfigFile(dynamic_binding_config_file, safe_copy_instance, role_name);
            is_dialog = false;
            Show();
        }

        /// <summary>
        /// 通过绑定状态配置文件生成模式对应框
        /// </summary>
        /// <param name="dynamic_binding_config_file">保存和还原动态绑定的文件</param>
        /// <param name="safe_copy_instance">安全拷贝，按确认才生效</param>
        /// <param name="role_name">角色名</param>
        /// <returns></returns>
        public bool? ShowDialogWinWithConfigFile(string dynamic_binding_config_file, bool safe_copy_instance = true, string? role_name = null)
        {
            //b_close.Visibility = safe_copy_instance ? Visibility.Visible : Visibility.Collapsed;
            cpanel.ShowControlsWithConfigFile(dynamic_binding_config_file, safe_copy_instance, role_name);
            is_dialog = true;
            return ShowDialog();
        }

        /// <summary>
        /// 显示对话框
        /// </summary>
        /// <param name="safe_copy_instance">安全拷贝，按确认才生效</param>
        /// <param name="role_name">角色名</param>
        /// <param name="binding_source">绑定列表</param>
        public void ShowWin(bool safe_copy_instance = true, string? role_name = null, DynamicBindingRoutePath[]? binding_source = null!)
        {
            //b_close.Visibility = safe_copy_instance ? Visibility.Visible : Visibility.Collapsed;
            cpanel.ShowControls(safe_copy_instance, role_name, binding_source);
            is_dialog = false;
            Show();
        }

        /// <summary>
        /// 显示模式对话框
        /// </summary>
        /// <param name="safe_copy_instance">安全拷贝，按确认才生效</param>
        /// <param name="role_name">角色名</param>
        /// <param name="binding_source">绑定列表</param>
        /// <returns></returns>
        public bool? ShowDialogWin(bool safe_copy_instance = true, string? role_name = null, DynamicBindingRoutePath[]? binding_source = null!)
        {
            //b_close.Visibility = safe_copy_instance ? Visibility.Visible : Visibility.Collapsed;
            cpanel.ShowControls(safe_copy_instance, role_name, binding_source);
            is_dialog = true;
            return ShowDialog();
        }

        /// <summary>
        /// 设置Panel控件标题宽度
        /// </summary>
        /// <param name="width"></param>
        public void SetPanelTitleWidht(double width)
        {
            cpanel.SetPanelTitleWidht(width);
        }

        /// <summary>
        /// 获取实际绑定对象
        /// </summary>
        /// <param name="binding_object">原始对象</param>
        /// <returns></returns>
        public object GetSetObject(object binding_object)
        {
            return cpanel.GetSetObject(binding_object);
        }

        /// <summary>
        /// 设置窗口图标
        /// </summary>
        /// <param name="icon">图标</param>
        public void SetFormIcon(System.Drawing.Icon icon)
        {
            this.Icon = Convert(icon.ToBitmap());
        }

        /// <summary>
        /// 设置窗口图标
        /// </summary>
        /// <param name="img">图标</param>
        public void SetFormIcon(System.Drawing.Image img)
        {
            this.Icon = Convert(img);
        }

        /// <summary>
        /// 位图转图像
        /// </summary>
        /// <param name="img">位图</param>
        /// <returns></returns>
        public static BitmapImage Convert(System.Drawing.Image img)
        {
            using (var memory = new MemoryStream())
            {
                img.Save(memory, ImageFormat.Png);
                memory.Position = 0;

                var bitmapImage = new BitmapImage();
                bitmapImage.BeginInit();
                bitmapImage.StreamSource = memory;
                bitmapImage.CacheOption = BitmapCacheOption.OnLoad;
                bitmapImage.EndInit();

                return bitmapImage;
            }
        }

        /// <summary>
        /// 获取基础面板控件
        /// </summary>
        /// <param name="header_name">大类别名</param>
        /// <param name="group_name">组名</param>
        /// <param name="property_path">上面对象的属性名</param>
        /// <returns></returns>
        public Controls.CreateControlBasePanel? GetPanel(string header_name, string group_name, string property_path)
        {
            return cpanel.GetPanel(header_name, group_name, property_path);
        }

        /// <summary>
        /// 获取对应生成的控件
        /// </summary>
        /// <param name="header_name">大类别名</param>
        /// <param name="group_name">组名</param>
        /// <param name="property_path">上面对象的属性名</param>
        /// <returns></returns>
        public T? GetPanelContent<T>(string header_name, string group_name, string property_path) where T : FrameworkElement
        {
            return cpanel.GetPanelContent<T>(header_name, group_name, property_path);
        }

        private void Close_Click(object sender, RoutedEventArgs e)
        {
            if (is_dialog)
                this.DialogResult = false;

            WinClosed?.Invoke(this, false);
            this.Close();
        }

        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            
        }

        private void OK_Click(object sender, RoutedEventArgs e)
        {
            cpanel.DynamicBindingNotification = DynamicBindingNotification;
            if (!cpanel.SaveUpdate(out string errmsg))
            {
                MessageBox.Show(errmsg, "必填项", MessageBoxButton.OK, MessageBoxImage.Stop);
                return;
            }
            if (is_dialog)
                this.DialogResult = true;

            WinClosed?.Invoke(this, true);
            this.Close();
        }

        private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
        {
            if (is_dialog && !this.DialogResult.HasValue)
                this.DialogResult = false;
        }
    }
}
